using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Net.Sockets;
using System.Windows.Threading;
using System.Windows.Media.Animation;


namespace OSCPacketVisualizer
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>

    public partial class Window1 : System.Windows.Window
    {

        public Window1()
        {
            InitializeComponent();

            Loaded += new RoutedEventHandler(Window1_Loaded);
            Closed += delegate { stop_thread = true; };

        }

        Thread thread;
        bool stop_thread;
        bool button_is_down;

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            thread = new Thread(ComThread);
            thread.Start();
        }

        void ComThread()
        {
            StringBuilder sb = new StringBuilder(4096);
            while (!stop_thread)
            {
                try
                {
                    TcpClient client = new TcpClient("localhost", 3000);
                    NetworkStream stream = client.GetStream();

                    while (!stop_thread)
                    {
                        char c = Convert.ToChar(stream.ReadByte());
                        if (c != '|')
                        {
                            sb.Append(c);
                        }
                        else
                        {
                            Dispatcher.Invoke(DispatcherPriority.Input, (Action<string>)PacketReceived, sb.ToString());
                            sb.Length = 0;
                        }
                    }
                }
                catch (Exception x)
                {
                    Debug.WriteLine(x.Message);
                    Thread.Sleep(1000);
                }
            }
        }

        void PacketReceived(string data)
        {
            this.Content = data;
            this.Content = "\n";
            /*
            bool button = data[0] == '*';
            double x = int.Parse(data.Substring(1, 4));
            double y = int.Parse(data.Substring(5, 4));

            Canvas.SetLeft(cursor, x);
            Canvas.SetTop(cursor, y);

            if (button) // ButtonDown
            {
                CreateAnimatedCircle(x, y);
            }
            */
        }

        private DateTime last_animated_circle = DateTime.UtcNow;

        static readonly Duration duration = new Duration(TimeSpan.FromSeconds(1.8));
        static readonly DoubleAnimation opacity = new DoubleAnimation(0, duration);
        static readonly DoubleAnimation scale = new DoubleAnimation(10, duration);

        readonly Queue<Ellipse> circles = new Queue<Ellipse>();

        void CreateAnimatedCircle(double x, double y)
        {
            if ((DateTime.UtcNow - last_animated_circle).Milliseconds < 60) return;

            last_animated_circle = DateTime.UtcNow;

            Ellipse e = new Ellipse();
            e.Width = 12;
            e.Height = 12;
            e.Fill = Brushes.BlueViolet;
            Canvas.SetLeft(e, x);
            Canvas.SetTop(e, y);
            canvas.Children.Add(e);
            
            ScaleTransform transform = new ScaleTransform(1, 1, 6, 6);
            e.RenderTransform = transform;
            transform.BeginAnimation(ScaleTransform.ScaleXProperty, scale);
            transform.BeginAnimation(ScaleTransform.ScaleYProperty, scale);
            e.BeginAnimation(OpacityProperty, opacity);   
            circles.Enqueue(e);
            if (circles.Count > 60)
            {
                canvas.Children.Remove(circles.Dequeue());
            }
        }

    }
}